﻿//
// Copyright (c) 2011 David Díaz & Fran Pedreira
//
// This file is part of PlanSim.
//
// PlanSim is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// PlanSim is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with PlanSim. If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using PlanSim.Core;

namespace PlanSim.Interfaz
{

    public partial class FormWizard : Form
    {
        public Configuracion configuracion;

        public FormWizard(Configuracion config)
        {
            InitializeComponent();
            configuracion = config;
        }

        private void FormWizard_Load(object sender, EventArgs e)
        {
            tc.SelectedIndex = 0;
            tc.Top = -22;
            tc.Left = -10;

            string s="";
           
            //nudNumeroCPU.Value=configuracion.NumeroProcesadores;
            if (configuracion.Estrategia == Configuracion.EstrategiaPlanificador.MLFQ)
            {
                rbMLFQ.Checked=true;
            }
            else 
            {
                rbMLQ.Checked = true;
            }

            for (int i = 0; i <= configuracion.Dispositivos.Count - 1; i++)
            {
                ListViewItem item1 = new ListViewItem(configuracion.Dispositivos[i].Nombre, 0);
                switch (configuracion.Dispositivos[i].TipoCola)
	            { case Configuracion.TipoCola.FCFS: s="FCFS";
                  break;
                        case Configuracion.TipoCola.RR: s="RR";
                  break;
                        case Configuracion.TipoCola.SJF: s="SJF";
                  break;
                        case Configuracion.TipoCola.SRT: s="SRT";
                  break;		        
	            }
                item1.SubItems.Add(s);
                item1.SubItems.Add(configuracion.Dispositivos[i].Quantum.ToString());

                lvES.Items.Add(item1);
            }

            for (int i = 0; i <= configuracion.Colas.Count - 1; i++)
            {
                ListViewItem item1 = new ListViewItem(configuracion.Colas[i].Nombre, 0);
                switch (configuracion.Colas[i].Tipo)
                {
                    case Configuracion.TipoCola.FCFS: s = "FCFS";
                        break;
                    case Configuracion.TipoCola.RR: s = "RR";
                        break;
                    case Configuracion.TipoCola.SJF: s = "SJF";
                        break;
                    case Configuracion.TipoCola.SRT: s = "SRT";
                        break;
                }
                item1.SubItems.Add(s);
                item1.SubItems.Add(configuracion.Colas[i].Quantum.ToString());
                
                lvColas.Items.Add(item1);
            }

            for (int i = 0; i <= configuracion.Procesos.Count - 1; i++)
            {
                ListViewItem item1 = new ListViewItem(configuracion.Procesos[i].Nombre, 0);
                item1.SubItems.Add(configuracion.Procesos[i].Entrada.ToString());
                item1.SubItems.Add(configuracion.Procesos[i].Duracion.ToString());
                item1.SubItems.Add(configuracion.Procesos[i].ColaInicial);
                if (configuracion.Procesos[i].AccesosADispositivos.Count > 0)
                {
                    item1.SubItems.Add("Si");
                
                }
                else
                {
                    item1.SubItems.Add("No");
                }
                lvProcesos.Items.Add(item1);
            }

        }
        private void bNext_Click(object sender, EventArgs e)
        {


            if (tc.SelectedIndex == 3)
            {
                if (lvProcesos.Items.Count == 0)
                {
                    MessageBox.Show("Configuración no completada. Al menos ha de especificar un proceso", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    this.DialogResult = DialogResult.OK;
                    validaConfiguracion();
                    Close();
                }

               
                

            }
            else
            {
                tc.SelectedIndex = tc.SelectedIndex + 1;
            }

        }

        private void bBack_Click(object sender, EventArgs e)
        {
            tc.SelectedIndex = tc.SelectedIndex - 1;


        }

        private void validaConfiguracion()
        {
            if (nudNumeroCPU.Value > 0 && nudNumeroCPU.Value < 2)
            {
                configuracion.NumeroProcesadores = decimal.ToInt32(nudNumeroCPU.Value);
            }
            else { configuracion.NumeroProcesadores = 1; }

            if (rbMLFQ.Checked)
            {
                configuracion.Estrategia = Configuracion.EstrategiaPlanificador.MLFQ;
            }
            if (rbMLQ.Checked)
            {
                configuracion.Estrategia = Configuracion.EstrategiaPlanificador.MLQ;
            }

            //Modificar, por ahora vamos a piñon ya que no aceptamos otras opciones de prioridades
            configuracion.PrioridadEnConcurrencia = 0;


            /*Tab de los dispositivos
             Añadimos a la clase configuración los cambios realizados en el tab*/
            configuracion.Dispositivos.Clear();
            for (int i = 0; i < lvES.Items.Count; i++)
            {
                string rNombre;
                Configuracion.TipoCola rEstrategia;
                int rQuantum;

                rNombre = lvES.Items[i].Text;
                rEstrategia = StringToTipoCola(lvES.Items[i].SubItems[1].Text);
                rQuantum = Int32.Parse(lvES.Items[i].SubItems[2].Text);

                Configuracion.Dispositivo dispositivo = new Configuracion.Dispositivo(rNombre, rEstrategia, rQuantum);
                configuracion.Dispositivos.Add(dispositivo);

            }


            /*Tab de las colas
             Añadimos a la clase configuración los cambios realizados en el tab*/
            configuracion.Colas.Clear();
            for (int i = 0; i < lvColas.Items.Count; i++)
            {
                string rNombre;
                Configuracion.TipoCola rEstrategia;
                int rQuantum;

                rNombre = lvColas.Items[i].Text;
                rEstrategia = StringToTipoCola(lvColas.Items[i].SubItems[1].Text);
                rQuantum = Int32.Parse(lvColas.Items[i].SubItems[2].Text);

                Configuracion.Cola cola = new Configuracion.Cola(rNombre, i, rEstrategia, rQuantum);
                configuracion.Colas.Add(cola);

            }

            

        }

        private Configuracion.TipoCola StringToTipoCola(string s)
        {
            Configuracion.TipoCola auxTipoCola = 0;
            if (s == "FCFS") auxTipoCola = Configuracion.TipoCola.FCFS;
            if (s == "RR") auxTipoCola = Configuracion.TipoCola.RR;
            if (s == "SJF") auxTipoCola = Configuracion.TipoCola.SJF;
            if (s == "SRT") auxTipoCola = Configuracion.TipoCola.SRT;
            return (auxTipoCola);
        }



        private void tc_SelectedIndexChanged(object sender, EventArgs e)
        {
            tPaso.Text = "Paso " + (tc.SelectedIndex + 1) + "/4";

            if (tc.SelectedIndex == 0)
            {
                bBack.Enabled = false;
            }
            else
            {
                bBack.Enabled = true;
            }
            if (tc.SelectedIndex == 3)
            {
                bNext.Text = "S&imular";

            }
            else { bNext.Text = "&Siguiente"; }
        }

        private void FormWizard_Shown(object sender, EventArgs e)
        {
            tc.SelectedIndex = 0;
            tc.Top = -22;
            tc.Left = -10;
        }

        private void bUpPriority_Click(object sender, EventArgs e)
        {
            /*lvPriority.Sorting = SortOrder.None;
            lvPriority.Items[0].Text = "3.- " + lvPriority.Items[0].ToolTipText;
            lvPriority.Items[1].Text = "1.- " + lvPriority.Items[1].ToolTipText;
            lvPriority.Items[2].Text = "2.- " + lvPriority.Items[2].ToolTipText;
            lvPriority.Sorting = SortOrder.Ascending;*/

        }

        private void bDownPriority_Click(object sender, EventArgs e)
        {

            /*lvPriority.Sorting = SortOrder.None;
            lvPriority.Items[0].Text = "2.- " + lvPriority.Items[0].ToolTipText;
            lvPriority.Items[1].Text = "3.- " + lvPriority.Items[1].ToolTipText;
            lvPriority.Items[2].Text = "1.- " + lvPriority.Items[2].ToolTipText;
            lvPriority.Sorting = SortOrder.Ascending;*/

        }

        /**
        * Métodos y eventos relacionados con el tab de Colas        
        */
        private void bAddCola_Click(object sender, EventArgs e)
        {

            FormCola form = new FormCola(lvColas.Items);
            form.Text = "Nueva cola";
            form.mode = 1;
            if (form.ShowDialog(this) == DialogResult.OK)
            {
                ListViewItem item1 = new ListViewItem(form.tNombre.Text, 0);
                item1.SubItems.Add(form.cb.Text);
                item1.SubItems.Add(form.tQuantum.Text);
                lvColas.Items.Add(item1);
            }
            form.Dispose();
        }

        private void bDelCola_Click(object sender, EventArgs e)
        {
            if (lvColas.SelectedItems.Count > 0)
            {
                ListView.SelectedIndexCollection indexes = lvColas.SelectedIndices;
                foreach (int index in indexes)
                {
                    if (colaEnUso(lvColas.Items[index].Text))
                    {
                        MessageBox.Show("Esta cola está configurada para ser usada por un proceso. No puede eliminarla.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    }
                    else
                    {
                        lvColas.Items.RemoveAt(index);
                    }
                }
            }

        }

        private bool colaEnUso(string s)
        {
            int i = 0;
            bool auxReturn = false;

            while (i <= configuracion.Procesos.Count - 1)
            {
                    if ((configuracion.Procesos[i].ColaInicial) == s)
                    {
                        auxReturn = true;
                        i = configuracion.Procesos.Count;

                    }
                    else
                    {
                        i++;
                    }

            }
            return (auxReturn);

        }





        private void tsbTop_Click(object sender, EventArgs e)
        {

            /*Sube al TOP la prioridad de una cola*/
            if (1 == lvColas.SelectedItems.Count)
            {
                ListViewItem item = lvColas.SelectedItems[0];
                int index = 0;
                if (index < lvColas.Items.Count)
                {
                    lvColas.Items.Remove(item);
                    lvColas.Items.Insert(index, item);
                    item.Selected = true;
                }
            }
        }

        private void tsDown_Click(object sender, EventArgs e)
        {
            /*Baja la prioridad de una cola*/
            if (1 == lvColas.SelectedItems.Count)
            {

                ListViewItem item = lvColas.SelectedItems[0];

                int index = item.Index;

                if (index < lvColas.Items.Count - 1)
                {
                    index++;
                }

                if (index < lvColas.Items.Count)
                {
                    
                    lvColas.Items.Remove(item);
                    lvColas.Items.Insert(index, item);
                    item.Selected = true;

                }

            }

        }

        private void tsbUp_Click(object sender, EventArgs e)
        {
            /*Sube la prioridad de una cola*/
            if (1 == lvColas.SelectedItems.Count)
            {

                ListViewItem item = lvColas.SelectedItems[0];

                int index = item.Index;
                if (index > 0)
                {
                    index--;
                }

                if (index < lvColas.Items.Count)
                {
                    lvColas.Items.Remove(item);
                    lvColas.Items.Insert(index, item);
                    item.Selected = true;
                }

            }
        }

        private void tsbBottom_Click(object sender, EventArgs e)
        {
            /*Baja al mínimo la prioridad de una cola*/
            if (1 == lvColas.SelectedItems.Count)
            {
                ListViewItem item = lvColas.SelectedItems[0];
                int index = lvColas.Items.Count - 1;

                if (index < lvColas.Items.Count)
                {
                    lvColas.Items.Remove(item);
                    lvColas.Items.Insert(index, item);
                    item.Selected = true;
                }
            }
        }

        private void lvColas_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            editarCola();
        }


        private void tsbEdit_Click(object sender, EventArgs e)
        {
            editarCola();
        }

        private void editarCola()
        {
            bool colEnUso = false;
         /*Edita el item selccionado*/
            if (1 == lvColas.SelectedItems.Count)
            {
                ListViewItem item = lvColas.SelectedItems[0];
                if (colaEnUso(item.Text))
                {
                    //MessageBox.Show("Esta cola está configurada para ser usada por un proceso. No puede modificarla", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    if (DialogResult.Yes == MessageBox.Show("Esta cola está configurada para ser usada en un proceso. ¿Desea editarla de todas formas", "Advertencia", MessageBoxButtons.YesNo, MessageBoxIcon.Warning))
                    {
                        colEnUso = true;
                    }
                    else
                    {
                        return;
                    }
                
                    FormCola form = new FormCola(lvColas.Items);
                    form.Text = "Editando cola";
                    form.mode = 2;
                    form.tNombre.Text = item.Text;
                    form.tNombre.Enabled = !colEnUso;
                    form.cb.Text = item.SubItems[1].Text;
                    form.tQuantum.Text = item.SubItems[2].Text;
                    if (form.ShowDialog(this) == DialogResult.OK)
                    {
                        item.Text = form.tNombre.Text;
                        item.SubItems[1].Text = form.cb.Text;
                        item.SubItems[2].Text = form.tQuantum.Text;
                    }
                    form.Dispose();
                    item.Selected = true;
                }
            }

        }

        /**
         * Métodos y eventos relacionados con el tab de Dispositivos         
         */


        private void tsAddDispo_Click(object sender, EventArgs e)
        {
            if (lvES.Items.Count == 0)
            {
                nuevoDispositivo();
            }
            else
            {
                MessageBox.Show("Esta versión solo admite un dispositivo", "Informacón", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void tsDelDispo_Click(object sender, EventArgs e)
        {
            if (lvES.SelectedItems.Count > 0)
            {
                ListView.SelectedIndexCollection indexes = lvES.SelectedIndices;
                foreach (int index in indexes)
                {
                    if (dispositivoEnUso(lvES.Items[index].Text))
                    {
                        MessageBox.Show("Este dispositivo está configurado para ser usado en un proceso. No puede eliminarlo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                
                    }
                    else
                    {
                        lvES.Items.RemoveAt(index);
                    }
                }
            }
        }

        private bool dispositivoEnUso(string s)
        {
            int i = 0;
            int j = 0;
            bool auxReturn=false;

            
            while (i <= configuracion.Procesos.Count-1) 
            {                
                while (j<=configuracion.Procesos[i].AccesosADispositivos.Count-1)
                {                    
                    if ((configuracion.Procesos[i].AccesosADispositivos[j].Dispositivo) == s)
                    {
                        auxReturn = true;
                        j = configuracion.Procesos[i].AccesosADispositivos.Count;
                        
                    }
                    else
                    {
                        j++;
                    }
                    
                }
                if (auxReturn)
                {
                    i = configuracion.Procesos.Count;
                }
                else
                {
                    i++;
                }
            }
            return (auxReturn);

        }



        private void tsTopDispo_Click(object sender, EventArgs e)
        {
            /*Sube al TOP la prioridad de un dispositivo*/
            if (1 == lvES.SelectedItems.Count)
            {
                ListViewItem item = lvES.SelectedItems[0];
                int index = 0;
                if (index < lvES.Items.Count)
                {
                    lvES.Items.Remove(item);
                    lvES.Items.Insert(index, item);
                    item.Selected = true;
                }
            }
        }

        private void tsUpDispo_Click(object sender, EventArgs e)
        {
            /*Sube la prioridad del dispositivo*/
            if (1 == lvES.SelectedItems.Count)
            {
                ListViewItem item = lvES.SelectedItems[0];
                int index = item.Index;
                if (index > 0)
                {
                    index--;
                }

                if (index < lvES.Items.Count)
                {
                    lvES.Items.Remove(item);
                    lvES.Items.Insert(index, item);
                    item.Selected = true;
                }
            }
        }

        private void tsDownDispo_Click(object sender, EventArgs e)
        {

            /*Baja la prioridad de un dispositivo*/
            if (1 == lvES.SelectedItems.Count)
            {
                ListViewItem item = lvES.SelectedItems[0];
                int index = item.Index;
                if (index < lvES.Items.Count - 1)
                {
                    index++;
                }

                if (index < lvES.Items.Count)
                {
                    lvES.Items.Remove(item);
                    lvES.Items.Insert(index, item);
                    item.Selected = true;
                }

            }

        }

        private void tsBottomDispo_Click(object sender, EventArgs e)
        {
            /*Baja al mínimo la prioridad de una cola*/
            if (1 == lvES.SelectedItems.Count)
            {
                ListViewItem item = lvES.SelectedItems[0];
                int index = lvES.Items.Count - 1;

                if (index < lvES.Items.Count)
                {
                    lvES.Items.Remove(item);
                    lvES.Items.Insert(index, item);
                    item.Selected = true;
                }
            }
        }

        private void nuevoDispositivo()
        {
  
            FormCola form = new FormCola(lvES.Items);
            form.Text = "Nuevo dispositivo";
            form.mode = 0;
            if (form.ShowDialog(this) == DialogResult.OK)
            {
                ListViewItem item1 = new ListViewItem(form.tNombre.Text, 0);
                item1.SubItems.Add(form.cb.Text);
                item1.SubItems.Add(form.tQuantum.Text);

                lvES.Items.Add(item1);

            }
            form.Dispose();  
        }


        private void tsEditDispo_Click(object sender, EventArgs e)
        {
            editarDispositivo();
        }

        private void editarDispositivo()
        {
           bool disEnUso=false;
            /*Edita el item seleccionado*/
            if (1 == lvES.SelectedItems.Count)
            {
                ListViewItem item = lvES.SelectedItems[0];
                if (dispositivoEnUso(item.Text))
                {
                    //MessageBox.Show("Este dispositivo está configurado para ser usado en un proceso. No puede modificarlo", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    if (DialogResult.Yes == MessageBox.Show("Este dispositivo está configurado para ser usado en un proceso. ¿Desea editarlo de todas formas", "Advertencia", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)) 
                    {
                        disEnUso=true;
                    }
                    else
                    {
                        return;
                    }

                }

                    FormCola form = new FormCola(lvES.Items);
                    form.Text = "Editando dispositivo";
                    form.mode = 2;
                    form.tNombre.Text = item.Text;
                    form.tNombre.Enabled = !disEnUso;
                    form.cb.Text = item.SubItems[1].Text;
                    form.tQuantum.Text = item.SubItems[2].Text;
                    if (form.ShowDialog(this) == DialogResult.OK)
                    {
                        item.Text = form.tNombre.Text;
                        item.SubItems[1].Text = form.cb.Text;
                        item.SubItems[2].Text = form.tQuantum.Text;
                    }
                    
                    form.Dispose();
                    item.Selected = true;

                

            } 
        }



        private void lvES_MouseDoubleClick(object sender, MouseEventArgs e)
        {
           
            if (1 == lvES.SelectedItems.Count)
            {
                editarDispositivo();
            }
      
        }



        /**
         * Métodos y eventos relacionados con el tab de Procesos         
         */
        private void tsbEditProc_Click(object sender, EventArgs e)
        {
           
        }

        private void editarProceso()
        {
            /*Edita el item seleccionado*/
            if (1 == lvProcesos.SelectedItems.Count)
            {
                ListViewItem item = lvProcesos.SelectedItems[0];
                Configuracion.Proceso proc = configuracion.Procesos[lvProcesos.SelectedItems[0].Index];

                FormProceso form = new FormProceso(proc);
                form.Text = "Editando proceso";
                form.mode = 2;
                form.tNomProceso.Text = item.Text;
                form.tEntrada.Text = item.SubItems[1].Text;
                form.tTCPU.Text = item.SubItems[2].Text;
                
                
                form.pColor.BackColor =System.Drawing.Color.FromArgb(proc.Color);
                
                if (form.ShowDialog(this) == DialogResult.OK)
                {
                    item.Text=form.tNomProceso.Text;  
                    item.SubItems[1].Text=form.tEntrada.Text; 
                    item.SubItems[2].Text=form.tTCPU.Text;
                    item.SubItems[3].Text = form.cbColaInicial.Text;
                    if (form.lvADis.Items.Count > 0)
                    {
                        item.SubItems[4].Text="Si";
                    }
                    else
                    {
                        item.SubItems[4].Text = "No";
                    }
                

                }
                form.Dispose();
                item.Selected = true;
            }   
        }

        private void toolStripButton8_Click(object sender, EventArgs e)
        {
            Configuracion.Proceso proceso = new Configuracion.Proceso();

            FormProceso form = new FormProceso(proceso);
            form.Text = "Nuevo proceso";
            if (form.ShowDialog(this) == DialogResult.OK)
            {
                ListViewItem item1 = new ListViewItem(form.tNomProceso.Text, 0);
                item1.SubItems.Add(form.tEntrada.Text);
                item1.SubItems.Add(form.tTCPU.Text);
                item1.SubItems.Add(form.cbColaInicial.Text);
                if (form.lvADis.Items.Count > 0)
                {
                    item1.SubItems.Add("Si");
                }
                else
                {
                    item1.SubItems.Add("No");
                }
                lvProcesos.Items.Add(item1);
                configuracion.Procesos.Add(proceso);
            }
            
            form.Dispose();

        }

        private void toolStripButton9_Click(object sender, EventArgs e)
        {
            if (lvProcesos.SelectedItems.Count > 0)
            {
                ListView.SelectedIndexCollection indexes = lvProcesos.SelectedIndices;
                foreach (int index in indexes)
                {
                    lvProcesos.Items.RemoveAt(index);
                    configuracion.Procesos.RemoveAt(index);
                }
            }

        }

        private void tsbEditProc_Click_1(object sender, EventArgs e)
        {
            editarProceso();
        }

        private void lvProcesos_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            editarProceso();
        }

  

  
    }
}

